package server.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import model.Usuario;
import server.exception.DAOException;
import server.exception.ServiceException;

public class UsuarioDAO {
	public static Connection conexion;

	public UsuarioDAO() {
		if (UsuarioDAO.conexion == null)
			UsuarioDAO.conexion = ConexionDAO.getInstance();
	}
	
	public void close() throws SQLException
	{
		UsuarioDAO.conexion.close();
	}

	/**
	 * Intenta hacer el Login del Usuario
	 * 
	 * @param username
	 * @param password
	 * @return 1 en caso de que el usuario y password sean correctas y su estado
	 *         sea 'ALTA'
	 * @return 0 en caso de que el usuario y password no coincidan
	 * @return -1 en caso de que el usuario y password sean correctas y su
	 *         estado sea 'BLOQUEADO'
	 * @return -2 en caso de que el usuario y password sean correctas y su
	 *         estado sea 'BAJA'
	 * @return 2 en caso de que el usuario y password sean correctas y su estado
	 *         sea 'ALTA'
	 * 
	 * @throws DAOException
	 */
	public Usuario login(String nick, String password) throws DAOException {
		try {
			String query = "SELECT id, nick, nombre, password, apellido, fecha_alta, pregunta_secreta, respuesta_secreta,estado"
					+ " FROM USUARIOS U "
					+ "WHERE U.nick = ? AND U.password = ? " +
					"AND NOT EXISTS (SELECT 1 FROM Penalizaciones P WHERE P.id_usuario = U.id AND fecha_fin > strftime('%s','now'));";
			
			PreparedStatement stmt = conexion.prepareStatement(query);
			stmt.setString(1, nick);
			stmt.setString(2, password);
			
			ResultSet result = stmt.executeQuery();
			
			Usuario user = new Usuario();
			if (result.next()) {
				user = new Usuario();
				user.setId(Integer.parseInt(result.getString("id")));
				user.setNombre(result.getString("nombre"));
				user.setApellido(result.getString("apellido"));
				user.setNick(result.getString("nick"));
				user.setPreguntaSecreta(result.getString("pregunta_secreta"));
				user.setRespuesta(result.getString("respuesta_secreta"));
				user.setFecha_alta(result.getString("fecha_alta"));
			}
			return user;
		} catch (SQLException e) {
			throw new DAOException("No se pudo realizar la accion", e);
		}
	}

	/**
	 * Obtiene el ultimo id insertado de la tabla usuarios
	 * 
	 * @return id
	 */
	public int getUltimoId() throws DAOException {
		try {

			Statement stmt = conexion.createStatement();
			ResultSet result = stmt
					.executeQuery("select last_insert_rowid() as last_id;");
			if (result.next()) {
				return Integer.parseInt(result.getString("last_id"));
			}
		} catch (SQLException e) {
			throw new DAOException("No se pudo realizar la accion", e);
		}
		return 1;
	}

	/**
	 * Busca un Usuario en la Base de Datos
	 * 
	 * @param id
	 * @return null si no existe el usuario
	 * @return Usuario si el usuario existe
	 * @throws DAOException
	 */
	public Usuario obtener(int id) throws DAOException {
		Usuario user = null;
		try {
			Statement stmt = conexion.createStatement();

			ResultSet result = stmt
					.executeQuery("SELECT id, nombre, apellido, nick, password, pregunta_secreta, respuesta_secreta, fecha_alta, estado FROM USUARIOS WHERE id  = "
							+ id + ";");
			if (result.next()) {
				user = new Usuario();
				user.setId(Integer.parseInt(result.getString("id")));
				user.setNombre(result.getString("nombre"));
				user.setApellido(result.getString("apellido"));
				user.setNick(result.getString("nick"));
				user.setPassword(result.getString("password"));
				user.setPreguntaSecreta(result.getString("pregunta_secreta"));
				user.setRespuesta(result.getString("respuesta_secreta"));
				user.setFecha_alta(result.getString("fecha_alta"));
				user.setPassword(result.getString("password"));
			}
		} catch (SQLException e) {
			throw new DAOException("No se pudo realizar la accion", e);
		}
		return user;

	}

	/**
	 * Busca un Usuario en la Base de Datos
	 * 
	 * @param id
	 * @return null si no existe el usuario
	 * @return Usuario si el usuario existe
	 * @throws DAOException
	 */
	public ArrayList<Usuario> buscar(String nombre, String apellido, String nick, Usuario usuario)
			throws DAOException {
		Usuario user = null;
		try {
			ArrayList<Usuario> encontrados = new ArrayList<Usuario>();
			Statement stmt = conexion.createStatement();

			ResultSet result = stmt
					.executeQuery("SELECT id, nombre, apellido, nick, " +
								  "password, pregunta_secreta, " +
								  "respuesta_secreta, fecha_alta, estado " +
								  "FROM USUARIOS a " +
								  "WHERE nombre LIKE '%"+ nombre + "%' " +
								  "AND apellido LIKE '%"+ apellido + "%' " +
								  "AND nick LIKE '%" + nick + "%' " +  
								 " AND NOT EXISTS(SELECT 1 " +
								 "				  FROM BLOQUEADOS c " +
								 "				  WHERE c.id_usuario = a.id "  +
								 "				  AND c.id_usuario_bloqueado = 	"+	usuario.getId() + ") ;");
			
			while (result.next()) {
				user = new Usuario();
				user.setId(Integer.parseInt(result.getString("id")));
				user.setNombre(result.getString("nombre"));
				user.setApellido(result.getString("apellido"));
				user.setNick(result.getString("nick"));
				user.setPassword(result.getString("password"));
				user.setPreguntaSecreta(result.getString("pregunta_secreta"));
				user.setRespuesta(result.getString("respuesta_secreta"));
				user.setFecha_alta(result.getString("fecha_alta"));
				user.setPassword("password");
				encontrados.add(user);
			}
			return encontrados;

		} catch (SQLException e) {
			throw new DAOException("No se pudo realizar la accion", e);
		}

	}
	
	public ArrayList<Usuario> amigosEnComun(Usuario u1, Usuario u2) throws DAOException {
		Usuario user = null;
	try {
		Statement stmt = conexion.createStatement();
		
		ResultSet result = stmt.executeQuery(
				"SELECT DISTINCT(id_amigo),u.id,u.nombre,u.apellido,u.nick,u.password " +
				"FROM USUARIOS as u, AMIGOS as a"  +
				"WHERE  a.id_amigo = u.id AND (a.id_user="+u1.getId()+" OR a.id_user = "+u2.getId()+")" +
				"UNION SELECT DISTINCT(id_user),u.id,u.nombre,u.apellido,u.nick,u.password" +
				"FROM USUARIOS as u, AMIGOS as a"  +
				"WHERE  a.id_user = u.id AND (a.id_amigo="+u1.getId()+" OR a.id_amigo = "+u2.getId()+")" 
				);
		ArrayList<Usuario> encontrados = new ArrayList<Usuario>();
		while (result.next()) {
			user = new Usuario();
			user.setId(Integer.parseInt(result.getString("id")));
			user.setNombre(result.getString("nombre"));
			user.setApellido(result.getString("apellido"));
			user.setNick( result.getString("nick"));
			user.setPassword(result.getString("password"));
			user.setPreguntaSecreta(result.getString("pregunta_secreta"));
			user.setRespuesta(result.getString("respuesta_secreta"));
			user.setFecha_alta(result.getString("fecha_alta"));
			user.setPassword("password");
			encontrados.add(user);
		}
		return encontrados;
		
	} catch (SQLException e) {
		throw new DAOException("No se pudo realizar la accion", e);
	}

}
	
	/**
	 * Inserta un usuario nuevo en la base de datos
	 * 
	 * @param usuario
	 * @throws DAOException
	 */
	public boolean guardar(Usuario usuario) throws DAOException {
		try {
			PreparedStatement st = conexion
					.prepareStatement("INSERT INTO USUARIOS "
							+ "(nombre, apellido, nick, password, pregunta_secreta, respuesta_secreta, fecha_alta,estado) "
							+ "values(?,?,?,?,?,?,?,'A');");
			st.setString(1, usuario.getNombre());
			st.setString(2, usuario.getApellido());
			st.setString(3, usuario.getNick());
			st.setString(4, usuario.getPassword());
			st.setString(5, usuario.getPreguntaSecreta());
			st.setString(6, usuario.getRespuesta());
			st.setTimestamp(7, new Timestamp(System.currentTimeMillis()));

			st.executeUpdate();

			return true;
			
		} catch (SQLException e) {			
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * Busca todos los usuarios de la lista
	 * 
	 * @return Lista de Usuarios en la base e datos
	 * @throws DAOException 
	 */
	public List<Usuario> todos() throws DAOException {
		List<Usuario> listaUsuarios = new ArrayList<Usuario>();
		try {
			Statement stmt = conexion.createStatement();
			ResultSet result = stmt
					.executeQuery("SELECT id, nombre, apellido, nick, pregunta_secreta FROM USUARIOS");
			while (result.next()) {
				Usuario user = new Usuario();
				user.setId(result.getInt("id"));
				user.setNombre(result.getString("nombre"));
				user.setApellido(result.getString("apellido"));
				user.setNick(result.getString("nick"));
				user.setPreguntaSecreta(result.getString("pregunta_secreta"));
				listaUsuarios.add(user);
			}
		} catch (SQLException e) {
			throw new DAOException("Hubo un problema al ejecutar la consulta", e);
		}
		return listaUsuarios;
	}

	/**
	 * Modifica el estado del usuario a 'b' (BAJA)
	 * 
	 * @param usuario
	 *            Usuario a eliminar
	 * @return true en caso de exito, false en caso contrario
	 * @throws ServiceException
	 *             En caso de que no se pueda concretar la accion
	 */
	public boolean eliminar(Usuario usuario) throws ServiceException {

		try {
			Statement st = conexion.createStatement();
			String update = "UPDATE USUARIO" + "SET estado = B" + "WHERE id = "
					+ usuario.getId() + ";";
			st.executeQuery(update);
			conexion.commit();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * Actualiza la informacion de un usuario existente
	 * 
	 * @param usuario
	 *            Usuario a actualizar sus datos
	 * @return true en caso de exito, false en caso contrario
	 * @throws ServiceException
	 *             En caso de que no se pueda concretar la accion
	 */
	public boolean actualizar(Usuario usuario) throws ServiceException {
		// TODO hacer actualizar
		return false;
	}

	/**
	 * Obtiene el usuario identificado por el nombre de usuario y contraseña
	 * pasado por parametro
	 * 
	 * @param username
	 *            Nombre de usuario
	 * @param password
	 *            Contraseña
	 * @return El usuario en caso de que exista, null en caso contrario
	 * @throws ServiceException
	 *             En caso de que no se pueda concretar la accion
	 */
	public Usuario obtener(String username, String password) throws ServiceException {
		Usuario user = null;
		Statement stmt;
		try {
			stmt = conexion.createStatement();
			ResultSet result = stmt.
					executeQuery("SELECT id ,nombre,apellido,nick," +
								 "		 password,pregunta_secreta," +
								 "		 respuesta_secreta " +
								 "FROM USUARIOS " +
								 "WHERE nick = '" + username + "';");
			while (result.next()) {
				user = new Usuario();
				user.setId(result.getInt("id"));
				user.setNombre(result.getString("nombre"));
				user.setApellido(result.getString("apellido"));
				user.setNick(result.getString("nick"));
				user.setPreguntaSecreta(result.getString("pregunta_secreta"));
				user.setRespuesta(result.getString("respuesta_secreta"));
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		return user;
	}
}
